package controller

import (
	"ETikTok/logic"
	"ETikTok/models"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"net/http"
	"os"
	"path/filepath"
	"strconv"

	"github.com/google/uuid"
)

// CreateVideoHandler 创建视频
func CreateVideoHandler(ctx *gin.Context) {
	// 1.获取参数及参数校验
	v := new(models.Video)
	/*if err := ctx.ShouldBind(v); err != nil {
		zap.L().Debug("ctx.ShouldBind(v) error", zap.Any("err", err))
		zap.L().Error("CreateVideo with invalid param", zap.Error(err))
		ResponseError(ctx, CodeInvalidParam)
		return
	}*/
	// 从ctx中获取当前发请求的用户的ID
	userID, err := getCurrentUserID(ctx)
	if err != nil {
		ResponseError(ctx, CodeNeedLogin)
		return
	}
	v.AuthorID = userID

	// 获取视频
	data, err := ctx.FormFile("video")
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{
			"msg": "投稿失败：" + err.Error(),
		})
		return
	}

	videoFileName := getUUID()
	// 将视频数据保存到指定位置
	videoFilePath := "./videos/" + videoFileName + ".mp4"

	targetDir := filepath.Dir(videoFilePath)
	if err := os.MkdirAll(targetDir, os.ModePerm); err != nil {
		ctx.JSON(http.StatusOK, gin.H{
			"status_code": 3,
			"status_msg":  "投稿失败：" + err.Error(),
		})
		return
	}

	//保存视频到服务器
	err = ctx.SaveUploadedFile(data, videoFilePath)
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{
			"status_code": 3,
			"status_msg":  "投稿失败：" + err.Error(),
		})
		return
	}

	v.VideoPath = videoFilePath
	// 获取表单中的 tag_id 参数
	tagIDStr := ctx.PostForm("tag_id")
	// 将字符串转换为 int64 类型
	tagID, err := strconv.ParseInt(tagIDStr, 10, 64)
	if err != nil {
		return
	}
	// 将转换后的 tagID 赋值给 v.TagID
	v.TagID = tagID
	v.Title = ctx.PostForm("title")
	v.Content = ctx.PostForm("content")

	// 2.业务处理,创建帖子
	if err := logic.CreateVideo(v); err != nil {
		zap.L().Error("logic.CreateVideo failed", zap.Error(err))
		ResponseError(ctx, CodeServerBusy)
		return
	}

	// 3.返回响应
	ResponseSuccess(ctx, nil)
}

// GetVideoDetailHandler 获取帖子详情
func GetVideoDetailHandler(ctx *gin.Context) {
	// 1.获取参数(从URL中获取帖子ID)
	pidStr := ctx.Param("id")
	pid, err := strconv.ParseInt(pidStr, 10, 64)
	if err != nil {
		zap.L().Error("get video detail with invalid param", zap.Error(err))
		ResponseError(ctx, CodeInvalidParam)
		return
	}

	// 2.业务处理(根据帖子ID查询帖子详情)
	data, err := logic.GetVideoById(pid)
	if err != nil {
		zap.L().Error("logic.GetVideoById failed", zap.Error(err))
		ResponseError(ctx, CodeServerBusy)
		return
	}

	// 3.返回响应
	ResponseSuccess(ctx, data)
}

// GetVideoListHandler 获取帖子列表
func GetVideoListHandler(ctx *gin.Context) {
	// 1.获取分页参数
	page, size := GetPageInfo(ctx)
	// 2.获取数据
	data, err := logic.GetVideoList(page, size)
	if err != nil {
		zap.L().Error("logic.GetVideoList failed", zap.Error(err))
		ResponseError(ctx, CodeServerBusy)
		return
	}
	// 3.返回响应
	ResponseSuccess(ctx, data)
}

// GetVideoListHandler2 获取帖子列表升级版
// 根据前端传来的参数动态获得帖子列表（按分数、按时间）
// 1.获取分页参数
// 2.去redis查询获取id列表
// 3.根据id去mysql查询帖子的详细信息
func GetVideoListHandler2(ctx *gin.Context) {
	// GET请求参数：page size order
	v := &models.ParamVideoList{
		Page:  1,
		Size:  10,
		Order: models.OrderTime,
	}

	if err := ctx.ShouldBindQuery(v); err != nil {
		zap.L().Error("GetVideoListHandler2 with invalid param", zap.Error(err))
		ResponseError(ctx, CodeInvalidParam)
		return
	}

	// 2.获取数据
	data, err := logic.GetVideoListNew(v) // 合并接口
	if err != nil {
		zap.L().Error("logic.GetVideoList failed", zap.Error(err))
		ResponseError(ctx, CodeServerBusy)
		return
	}
	// 3.返回响应
	ResponseSuccess(ctx, data)
}

/*// GetTagVideoListHandler 获取社区帖子列表
func GetTagVideoListHandler(ctx *gin.Context) {
	// GET请求参数：page size order
	v := &models.ParamTagVideoList{
		ParamVideoList: models.ParamVideoList{
			Page:  1,
			Size:  10,
			Order: models.OrderTime,
		},
	}

	if err := ctx.ShouldBindQuery(v); err != nil {
		zap.L().Error("GetTagVideoListHandler with invalid param", zap.Error(err))
		ResponseError(ctx, CodeInvalidParam)
		return
	}
	// 2.获取数据
	data, err := logic.GetTagVideoList(v)
	if err != nil {
		zap.L().Error("logic.GetTagVideoListHandler failed", zap.Error(err))
		ResponseError(ctx, CodeServerBusy)
		return
	}
	// 3.返回响应
	ResponseSuccess(ctx, data)
}
*/

func getUUID() string {
	// 生成 UUID 作为文件名
	uuid := uuid.New()
	uuidFileName := uuid.String()
	return uuidFileName
}
